package com.speedata;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.speedata.libutils.DataConversionUtils;
import com.speedata.uhftest.R;
import com.speedata.utils.Logcat;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author xuyan  读电话号码并显示,用原H6的读取方式读对应参数
 */
public class LuyinActivity extends AppCompatActivity implements View.OnClickListener {


    private RecordTask recorder;
    private PlayTask player;
    private File fpath;
    private File audioFile;
    private boolean isRecording = true, isPlaying = false; // 标记
    private final int frequence = 16000;// 8000;
    // //录制频率，单位hz.这里的值注意了，写的不好，可能实例化AudioRecord对象的时候，会出错。我开始写成11025就不行。这取决于硬件设备
    private final int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    private final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    private boolean isPlay = false;
    private boolean isStart = false;

    private TextView tvInfor;
    /**
     * 开始录音
     */
    private Button btnSoundRecording;
    /**
     * 播放录音
     */
    private Button btnPlay;


    //存储计时
    private int numTime;
    //存储倒计时
    private int reTime;

    private Button bt3;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_luyin);
        initView();

        AudioManager audioManager = (AudioManager) this.getSystemService(Service.AUDIO_SERVICE);
        int max = audioManager
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                max, 0);
        btnPlay.setOnClickListener(this);
        btnPlay.setEnabled(false);

        btnSoundRecording.setText("开始录音");
        btnSoundRecording.setOnClickListener(this);
        btnPlay.setText("播放录音");

        AudioManager audioManager1=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);

//        registerHeadsetPlugReceiver();
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED))// 手机有SD卡的情况
        {
            // 在这里我们创建一个文件，用于保存录制内容
            fpath = new File(Environment.getExternalStorageDirectory()
                    .getAbsolutePath() + "/data/files/");
            fpath.mkdirs();// 创建文件夹
        } else// 手机无SD卡的情况
        {
            fpath = this.getCacheDir();
        }

        try {
            // 创建临时文件,注意这里的格式为.pcm
            audioFile = File.createTempFile("recording", ".pcm", fpath);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        bt3 = findViewById(R.id.bt3);
        bt3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO: 2022/3/23/023  转换并打印

                byte[] a = File2byte(audioFile.getAbsoluteFile());

                Logcat.d("LUYIN", DataConversionUtils.byteArrayToString(a));
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isPlaying = false;
        fpath = null;
        audioFile = null;
        if (recorder != null) {
            recorder.cancel(true);
            recorder = null;
        }
        if (player != null) {
            player.cancel(true);
            player = null;
        }

    }

    @Override
    protected void onPause() {
        //如果异步任务不为空 并且状态是 运行时  ，就把他取消这个加载任务
        if (player != null && player.getStatus() == AsyncTask.Status.RUNNING) {
            player.cancel(true);

        }
        super.onPause();
    }

    //添加计时
    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @SuppressLint("SetTextI18n")
        @Override
        public void run() {
            numTime++;
            tvInfor.setText("录音时长" + numTime + "s");
            handler.postDelayed(this, 1000);
        }
    };
    //添加倒计时
    Runnable runnable2 = new Runnable() {
        @SuppressLint("SetTextI18n")
        @Override
        public void run() {
            reTime--;
            tvInfor.setText("剩余时长" + reTime + "s");
            handler.postDelayed(this, 1000);
        }
    };

    @SuppressLint("SetTextI18n")
    @Override
    public void onClick(View v) {
        if (v == btnSoundRecording) {
            if (!isStart) {
                recorder = new RecordTask();
                recorder.execute();//执行计时
                isStart = true;
                btnSoundRecording.setText("结束录音");
                numTime = 0;
                tvInfor.setText("录音时长" + numTime + "s");
            } else {
                this.isRecording = false;
                btnSoundRecording.setText("开始录音");
                isStart = false;
            }

        } else if (v == btnPlay) {

            if (!isPlay) {
                player = new PlayTask();
                btnPlay.setText("停止播放");
                player.execute();
                isPlay = true;
                reTime = numTime;
                tvInfor.setText("剩余时长" + reTime + "s");
            } else {
                isPlay = false;
                btnPlay.setText("播放");
                this.isPlaying = false;
                handler.removeCallbacks(runnable2);
            }
        }

    }

    private void initView() {

        tvInfor = findViewById(R.id.tv_infor);
        btnSoundRecording = findViewById(R.id.btn_sound_recording);
        btnSoundRecording.setOnClickListener(this);
        btnPlay = findViewById(R.id.btn_play);

    }


    @SuppressLint("StaticFieldLeak")
    class RecordTask extends AsyncTask<Void, Integer, Void> {
        @SuppressLint("UseValueOf")
        @Override
        protected Void doInBackground(Void... arg0) {
            isRecording = true;
            if (isCancelled()) {
                return null;
            }
            try {
                // 开通输出流到指定的文件
                DataOutputStream dos = new DataOutputStream(
                        new BufferedOutputStream(
                                new FileOutputStream(audioFile)));
                // 根据定义好的几个配置，来获取合适的缓冲大小
                int bufferSize = AudioRecord.getMinBufferSize(frequence,
                        channelConfig, audioEncoding);
                AudioRecord record = null;

                // 实例化AudioRecord
                record = new AudioRecord(
                        MediaRecorder.AudioSource.MIC, frequence,
                        channelConfig, audioEncoding, bufferSize);


                // 定义缓冲
                short[] buffer = new short[bufferSize];

                // 开始录制
                record.startRecording();
                handler.postDelayed(runnable, 0);
                int r = 0; // 存储录制进度
                // 定义循环，根据isRecording的值来判断是否继续录制
                while (isRecording) {
                    // 从bufferSize中读取字节，返回读取的short个数
                    // 这里老是出现buffer overflow，不知道是什么原因，试了好几个值，都没用，TODO：待解决
                    int bufferReadResult = record
                            .read(buffer, 0, buffer.length);
                    // 循环将buffer中的音频数据写入到OutputStream中
                    for (int i = 0; i < bufferReadResult; i++) {
                        dos.writeShort(buffer[i]);
                    }
                    publishProgress(r); // 向UI线程报告当前进度
                    r++; // 自增进度值
                }
                // 录制结束
                record.stop();
                handler.removeCallbacks(runnable);
                Log.v("The DOS available:", "::" + audioFile.length());
                dos.close();
            } catch (Exception e) {
                // TODO: handle exception
            }
            return null;
        }

        // 当在上面方法中调用publishProgress时，该方法触发,该方法在I线程中被执行
        @Override
        protected void onProgressUpdate(Integer... progress) {
//            tvInfor.setText(progress[0].toString());
        }

        @Override
        protected void onPostExecute(Void result) {
            btnPlay.setEnabled(true);
        }

        @Override
        protected void onPreExecute() {
            btnPlay.setEnabled(false);
        }
    }

    @SuppressLint("StaticFieldLeak")
    class PlayTask extends AsyncTask<Void, Integer, Void> {
        @Override
        protected Void doInBackground(Void... arg0) {
            if (isCancelled()) {
                return null;
            }
            isPlaying = true;
            int bufferSize = AudioTrack.getMinBufferSize(frequence,
                    channelConfig, audioEncoding);
            short[] buffer = new short[bufferSize / 4];
            try {
                // 定义输入流，将音频写入到AudioTrack类中，实现播放
                DataInputStream dis = new DataInputStream(
                        new BufferedInputStream(new FileInputStream(audioFile)));
                // 实例AudioTrack
                AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
                        frequence, channelConfig, audioEncoding, bufferSize,
                        AudioTrack.MODE_STREAM);
                // 开始播放
                track.play();
                //循环写入似乎比循环播放时间稍长，为了计时器能减到0，所以将第一次提前开始计时
                handler.postDelayed(runnable2, 0);
                // 由于AudioTrack播放的是流，所以，我们需要一边播放一边读取
                while (isPlaying && dis.available() > 0) {
                    int i = 0;
                    while (dis.available() > 0 && i < buffer.length) {
                        buffer[i] = dis.readShort();
                        i++;
                    }
                    // 然后将数据写入到AudioTrack中
                    track.write(buffer, 0, buffer.length);
                }

                // 播放结束
                track.stop();
                handler.removeCallbacks(runnable2);
                dis.close();

            } catch (Exception e) {
                // TODO: handle exception
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            isPlay = false;
            btnPlay.setText("播放");
            btnSoundRecording.setEnabled(true);
        }

        @Override
        protected void onPreExecute() {
            btnSoundRecording.setEnabled(false);
        }
    }


    /**
     * 将文件转换成byte数组
     * @param tradeFile 要转换的文件路径
     * @return
     */
    public static byte[] File2byte(File tradeFile){
        byte[] buffer = null;
        try
        {
            FileInputStream fis = new FileInputStream(tradeFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1)
            {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (IOException e){
            e.printStackTrace();
        }
        return buffer;
    }

}
